<?php

namespace app\company\controller;

use app\common\enum\Status;
use app\common\exception\BaseException;
use app\common\model\DealerGoods as DealerGoodsModel;
use app\common\controller\CompanyController;
use app\common\model\Dealer as DealerModel;
use app\common\model\DealerGoodsSpec;
use app\common\model\GoodsBrand;
use app\common\model\GoodsCate;
use app\common\service\annotation\ControllerAnnotation;
use app\common\service\annotation\NodeAnnotation;
use app\company\model\CompanyUser;
use app\Request;
use jianyan\excel\Excel;
use think\App;
use think\facade\Db;
use think\response\Json;

/**
 * @ControllerAnnotation(title="经销商商品管理")
 */
class DealerGoods extends CompanyController
{
    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->model           = new DealerGoodsModel();
        $this->sort = ['warehouse_stock' => 'desc','sales_stock' => 'desc','id' => 'desc'];
        $this->joinAddTable    = 'spec';
        $this->joinUpdateTable = 'spec';
        $this->joinDelTable    = 'spec';
        $this->each            = true;
        $this->fileName        = '商品模版';
        $this->defaultTemplate = [
                'name', 'dealer_name', 'code69', 'brand_name', 'cate_name', 'shelf_life_day', 'warehouse_warn_day', 'retention_warn_day', 'expiration_warn_day',
                'min_unit', 'min_name', 'min_sku', 'min_purchase_price', 'min_sale_price', 'min_quantity', 'min_unit_convert',
                'min_length', 'min_width', 'min_height', 'min_weight', 'min_driver_money', 'min_salesman_money', 'min_remark',
                'max_unit', 'max_name', 'max_sku', 'max_purchase_price', 'max_sale_price', 'max_quantity', 'max_unit_convert',
                'max_length', 'max_width', 'max_height', 'max_weight', 'max_driver_money', 'max_salesman_money', 'max_remark',
                'mid_unit', 'mid_name', 'mid_sku', 'mid_purchase_price', 'mid_sale_price', 'mid_quantity', 'mid_unit_convert',
                'mid_length', 'mid_width', 'mid_height', 'mid_weight', 'mid_driver_money', 'mid_salesman_money', 'mid_remark'
        ];
        $this->importHeader    = [
                '商品名称*', '经销商名称*', '商品条码*', '品牌*', '分类*', '保质期(天)', '入库预警(天)', '滞留预警(天)', '临期预警(天)',
                '单位名称(小)*', '规格(小)*', 'SKU(小)*', '进价(小)', '售价(小)*', '起购数(小)', '换算比例(小)*',
                '长(小)(cm)', '宽(小)(cm)', '高(小)(cm)', '重量(小)(kg)', '配送费用(小)', '业务提成(小)', '备注(小)',
                '单位名称(大)', '规格(大)', 'SKU(大)', '进价(大)', '售价(大)', '起购数(大)', '换算比例(大)',
                '长(大)(cm)', '宽(大)(cm)', '高(大)(cm)', '重量(大)(kg)', '配送费用(大)', '业务提成(大)', '备注(大)',
                '单位名称(中)', '规格(中)', 'SKU(中)', '进价(中)', '售价(中)', '起购数(中)', '换算比例(中)',
                '长(中)(cm)', '宽(中)(cm)', '高(中)(cm)', '重量(中)(kg)', '配送费用(中)', '业务提成(中)', '备注(中)'
        ];

        $this->noExportFields = [
                  'goods_id','company_id','dealer_cate_id','dealer_brand_id','storage_condition','image',
                  'status','create_time','update_time','delete_time'
        ];
    }

    public function each($list)
    {
        return $list->each(function ($vo)
        {
            $this->dealStock($vo);
            $vo->spec   = $vo->spec()->select();
            $vo->brand  = $vo->brand()->find();
            $vo->cate   = $vo->cate()->find();
            $vo->dealer = $vo->dealer()->find();
            $vo->creator = (new CompanyUser())->where('id',$vo->creator_id)->value('username')??'无';
            $vo->batch  = $vo->batch ? json_decode($vo->batch, true) : [];
            return $vo;
        });
    }

    public function dealStock($vo): void
    {
        $spec = json_decode($vo->spec()->select(), true);
        usort($spec, function ($a, $b) {
            return $b['ratio'] <=> $a['ratio'];  // 使用太空船操作符进行升序排序
        });
        $sales_str = $warehouse_str = '';
        $sales_stock = $old_sales_stock = $vo->sales_stock;
        $warehouse_stock = $old_warehouse_stock = $vo->warehouse_stock;
        $unit = '';
        foreach ($spec as $value){
            if(!$value['ratio']) continue;
            // 售卖库存
            $sales_quotient = intdiv($sales_stock, $value['ratio']);
            $sales_stock = $sales_stock % $value['ratio'];
            $sales_str .= $sales_quotient.$value['unit'];
            // 库内库存
            $warehouse_quotient = intdiv($warehouse_stock, $value['ratio']);
            $warehouse_stock = $warehouse_stock % $value['ratio'];
            $warehouse_str .= $warehouse_quotient.$value['unit'];
            if($value['unit_type'] == 1) $unit = $value['unit'];
        }
        $vo->sales_stock = $sales_str.' = '.$old_sales_stock.$unit;
        $vo->warehouse_stock = $warehouse_str.' = '.$old_warehouse_stock.$unit;
    }

    /**
     * @NodeAnnotation(title="新增")
     */
    public function add(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $post['company_id'] = $this->companyId;
        $post['creator_id'] = $this->uid;
        $rule = [
            'company_id|公司ID' => 'require',
            'spec|规格信息' => 'require',
        ];
        $this->validate($post, $rule);
        try {
            $this->model->transaction(function () use ($post)
            {
                $this->model->save($post);
                // 如果有需要添加的关联表数据
                if ($this->joinAddTable) $this->joinAddTable($post);
            });
        } catch (\Exception $e) {
            return $this->error('新增失败:' . $e->getMessage());
        }
        return $this->success('新增成功');
    }

    /**
     * @NodeAnnotation(title="编辑")
     */
    public function edit(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $rule = [
            'id' => 'require|integer'
        ];
        $this->validate($post, $rule);
        $row = $this->model->find($post['id']);
        if (!$row) return $this->error('数据不存在！');
        try {
            $this->model->transaction(function () use ($post, $row)
            {
//                $detail = json_decode($post['spec'], true);
//                foreach ($detail as &$vo) {
//                    if($vo['unit_type'] == 1) $vo['ratio'] = 1;
//                }
                $row->save($post);
                // 如果有需要更新的关联表数据
                if ($this->joinUpdateTable) $this->joinUpdateTable($post, $row);
            });
        } catch (\Exception $e) {
            return $this->error('保存失败:' . $e->getMessage());
        }
        return $this->success('保存成功');
    }

    /**
     * @NodeAnnotation(title="导入")
     */
    public function import(Request $request): Json
    {
        $this->model->startTrans();
        try {
            $this->checkPost();
            $file = $request->file('file');
            if (!$file) return $this->error('请上传文件！');
            // 保存文件到临时目录
            $savePath = $file->move('storage' . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR);
            // 获取文件的完整路径
            $savePath = $savePath->getPathname();
            $data     = Excel::import($savePath, 1, false, 'Xlsx', './storage/temp/excelImg/');
            if (!$data) throw new BaseException(['message' => '文件内容为空！']);
            if (!$this->importHeader) throw new BaseException(['message'=>'请联系管理设置文件模版']);
            if (array_filter($data[0]) != $this->importHeader)  throw new BaseException(['message'=>'文件格式不正确']);
            unset($data[0]);
            $data = array_filter($data);
            $this->dealGoods($data);
            @unlink($savePath);
        } catch (\Exception $e) {
            $this->model->rollback();
            return $this->error('导入失败！' . $e->getMessage());
        }
        $this->model->commit();
        return $this->success('导入成功！');
    }

    /**
     * 处理商品数据
     * @throws BaseException
     */
    private function dealGoods(mixed $info): void
    {
        if (empty($info)) throw new BaseException(['message' => '文件内容为空！']);
        array_walk($info, function ($vo)
        {
            $fields = $this->defaultTemplate;
            // 将$fields中的值对应到$vo上的键
            $data = array_combine($fields, $vo);
            // 定义验证器
            $rule = [
                    'name|商品名称'           => 'require',
                    'dealer_name|经销商名称'  => 'require',
                    'code69|商品条码'         => 'require',
                    'brand_name|品牌'         => 'require',
                    'cate_name|分类'          => 'require',
                    'min_unit|单位名称(小)'   => 'require',
                    'min_name|规格(小)'       => 'require',
                    'min_sale_price|单价(小)' => 'require',
            ];
            // 批量验证
            $this->validate($data, $rule);
            $goods = [
                    'name'                => $data['name'],
                    'code69'              => $data['code69'],
                    'shelf_life_day'      => $data['shelf_life_day'],
                    'warehouse_warn_day'  => $data['warehouse_warn_day'],
                    'retention_warn_day'  => $data['retention_warn_day'],
                    'expiration_warn_day' => $data['expiration_warn_day']
            ];
            // 组装数据
            $goods['dealer_id'] = DealerModel::where('name', $data['dealer_name'])
                                             ->where('company_id', $this->companyId)->value('id') ?? 0;
            if (!$goods['dealer_id']) throw new BaseException(["message" => "经销商【{$data['dealer_name']}】不存在！"]);
            $goods['brand_id'] = GoodsBrand::where('name', $data['brand_name'])->value('id') ?? 0;
            if (!$goods['brand_id']) throw new BaseException(["message" => "品牌【{$data['brand_name']}】不存在！"]);
            $goods['cate_id'] = GoodsCate::where('name', $data['cate_name'])->value('id') ?? 0;
            if (!$goods['cate_id']) throw new BaseException(["message" => "分类【{$data['cate_name']}】不存在！"]);
            $goods['company_id'] = $this->companyId;
            // 规格
            $spec[] = [
                    'dealer_id'      => $goods['dealer_id'],
                    'unit_type'      => 1,
                    'unit_name'      => $data['min_unit'],
                    'name'           => $data['min_name'],
                    'sku'            => $data['min_sku'],
                    'purchase_price' => $data['min_purchase_price'],
                    'sale_price'     => $data['min_sale_price'],
                    'min_quantity'   => $data['min_quantity'],
                    'unit_convert'   => $data['min_unit_convert'],
                    'length'         => $data['min_length'],
                    'width'          => $data['min_width'],
                    'height'         => $data['min_height'],
                    'weight'         => $data['min_weight'],
                    'driver_money'   => $data['min_driver_money'],
                    'salesman_money' => $data['min_salesman_money'],
                    'remark'         => $data['min_remark'],
            ];

            if ($data['max_unit'] && $data['max_name']) {
                $spec[] = [

                        'dealer_id'      => $data['dealer_id'],
                        'unit_type'      => 2,
                        'unit_name'      => $data['max_unit'],
                        'name'           => $data['max_name'],
                        'sku'            => $data['max_sku'],
                        'purchase_price' => $data['max_purchase_price'],
                        'sale_price'     => $data['max_sale_price'],
                        'min_quantity'   => $data['max_quantity'],
                        'unit_convert'   => $data['max_unit_convert'],
                        'length'         => $data['max_length'],
                        'width'          => $data['max_width'],
                        'height'         => $data['max_height'],
                        'weight'         => $data['max_weight'],
                        'driver_money'   => $data['max_driver_money'],
                        'salesman_money' => $data['max_salesman_money'],
                        'remark'         => $data['max_remark'],
                ];
            }

            if ($data['mid_unit'] && $data['mid_name']) {
                $spec[] = [
                        'dealer_id'      => $goods['dealer_id'],
                        'unit_type'      => 3,
                        'unit_name'      => $data['mid_unit'],
                        'name'           => $data['mid_name'],
                        'sku'            => $data['mid_sku'],
                        'purchase_price' => $data['mid_purchase_price'],
                        'sale_price'     => $data['mid_sale_price'],
                        'min_quantity'   => $data['mid_quantity'],
                        'unit_convert'   => $data['mid_unit_convert'],
                        'length'         => $data['mid_length'],
                        'width'          => $data['mid_width'],
                        'height'         => $data['mid_height'],
                        'weight'         => $data['mid_weight'],
                        'driver_money'   => $data['mid_driver_money'],
                        'salesman_money' => $data['mid_salesman_money'],
                        'remark'         => $data['mid_remark']
                ];
            }
            // 查询商品是否存在
            $row = $this->model->where('code69', $goods['code69'])->findOrEmpty();
            // 如果不存在插入新数据
            if ($row->isEmpty()) {
                $model = (new DealerGoodsModel());
                $model->save($goods);
                // 插入规格
                $model->spec()->saveAll($spec);
            }
        });
    }

    /**
     * @NodeAnnotation(title="删除商品规格")
     * @throws BaseException
     */
    public function delSpec(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $rule = [
                'id' => 'require|integer'
        ];
        $this->validate($post, $rule);
        try {
            $row = DealerGoodsSpec::find($post['id']);
            if ($row) $row->delete();
        } catch (\Exception $e) {
            return $this->error('删除失败:' . $e->getMessage());
        }
        return $this->success('删除成功');
    }

    /**
     * @NodeAnnotation(title="导出")
     */
    public function export(): bool
    {
        // 构建查询
        list($limit, $where) = $this->buildSearchParams();
        // 获取表名
        $tableName = $this->model->getName();
        $tableName = humpToLine(lcfirst($tableName));
        // 获取表前缀
        $prefix = config('database.connections.mysql.prefix');
        // 获取表字段
        $dbList = Db::query("show full columns from {$prefix}{$tableName}");
        // 设置表头
        $header = [];
        // 循环表字段
        foreach ($dbList as $vo) {
            $comment = !empty($vo['Comment']) ? $vo['Comment'] : $vo['Field'];
            if($vo['Field'] == 'dealer_id') $comment = '经销商';
            if($vo['Field'] == 'brand_id') $comment = '品牌';
            if($vo['Field'] == 'cate_id') $comment = '分类';
            if (!in_array($vo['Field'], $this->noExportFields)) {
                $header[] = [$comment, $vo['Field']];
            }
        }
        $list     = $this->model
                ->where($where)
                ->where($this->defaultWhere)
                ->where('status', Status::NORMAL)
                ->limit($limit ?? 100000)
                ->order(['warehouse_stock'=>'desc','sales_stock'=>'desc','id'=>'desc'])
                ->select()->each(function ($item){
                    $item->cate_id = $item->cate()->value('name');
                    $item->brand_id = $item->brand()->value('name');
                    $item->dealer_id = $item->dealer()->value('name');
                    $this->dealStock($item);
                })
                ->toArray();
        $fileName = time();
        return Excel::exportData($list, $header, $fileName, 'xlsx');
    }
}